home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / _archvrs / unix / unzip51 / mapname.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-04  |  15.1 KB  |  389 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   mapname.c
  4.  
  5.   This routine changes TOPS-20, VMS, and MSDOS-style filenames into normal
  6.   Unix names (and vice versa, in some cases); it also creates any necessary 
  7.   directories, unless the -j switch was specified.
  8.  
  9.   ---------------------------------------------------------------------------
  10.  
  11.   Notes:
  12.  
  13.    - This routine REALLY needs to be rewritten (different routines for each
  14.      output OS, with different rules for different parts of the path name).
  15.    - The strcpy and strcat operations on both cdp and filename may overwrite
  16.      memory, since they don't check lengths.  With a kilobyte in which to
  17.      work, this is probably not that big a deal, but it could cause problems
  18.      eventually.
  19.  
  20.   ---------------------------------------------------------------------------*/
  21.  
  22.  
  23. #include "unzip.h"
  24.  
  25.  
  26. /*******************/
  27. /* Mapname Defines */
  28. /*******************/
  29.  
  30. #ifdef VMS
  31. #  define PERMS   0
  32. #else
  33. #  define PERMS   0777
  34. #endif
  35.  
  36. #ifndef NO_MKDIR
  37. #  if defined(DOS_OS2) && (!defined(__GO32__))
  38. #    if (_MSC_VER >= 600)          /* have special MSC mkdir prototype */
  39. #      include <direct.h>
  40. #    else                          /* own prototype because dir.h conflicts? */
  41.        int mkdir(const char *path);
  42. #    endif /* ?(MSC 6.0 or later) */
  43. #    define MKDIR(path,mode)   mkdir(path)
  44. #  else /* !DOS_OS2 || __GO32__ */
  45. #    ifdef MACOS
  46. #      define MKDIR(path,mode)     macmkdir(path,gnVRefNum,glDirID)
  47. #    else /* !MACOS */
  48. #      ifdef AMIGA
  49. #        define MKDIR(path,mode)   mkdir(path)
  50. #      else /* !AMIGA */
  51. #        define MKDIR(path,mode)   mkdir(path,mode)
  52. #      endif /* ?AMIGA */
  53. #    endif /* ?MACOS */
  54. #  endif /* ?(DOS_OS2 && !__GO32__) */
  55. #endif /* !NO_MKDIR */
  56.  
  57.  
  58.  
  59.  
  60. /************************/
  61. /*  Function mapname()  */
  62. /************************/
  63.  
  64. int mapname(create_dirs)   /* return 0 if no error, 1 if caution (filename */
  65.     int create_dirs;       /*  truncated), 2 if warning (skip file because */
  66. {                          /*  dir doesn't exist), 3 if error (skip file) */
  67. #if defined(NO_MKDIR) && (!defined(TOPS20))
  68.     char command[FILNAMSIZ+40]; /* buffer for system() call */
  69. #endif
  70. #ifdef DOS_T20_VMS
  71.     char *last_dot=NULL;        /* last dot not converted to underscore */
  72. #ifdef T20_VMS
  73.     int stat_val;               /* temp. holder for stat() return value */
  74.     char *dp, *xp;              /* pointers to directory name */
  75. #ifdef VMS
  76.     char *np;                   /* pointer into filename */
  77. #endif /* VMS */
  78. #endif /* T20_VMS */
  79. #endif /* DOS_T20_VMS */
  80. #ifdef OS2
  81.     char *last;
  82.     int longdir;
  83. #endif /* OS2 */
  84.     char name[FILNAMSIZ];       /* file name buffer */
  85.     char *pp, *cp, *cdp;        /* character pointers */
  86.     char delim = '\0';          /* directory delimiter */
  87.     int quote = FALSE;          /* flags */
  88.     int indir = FALSE;
  89.     int done = FALSE;
  90.     int created = FALSE;
  91.     register unsigned workch;   /* hold the character being tested */
  92.  
  93.  
  94. /*---------------------------------------------------------------------------
  95.     Initialize various pointers and counters and stuff.
  96.   ---------------------------------------------------------------------------*/
  97.  
  98. #ifdef MAP_DEBUG
  99.     fprintf(stderr, "%s ", filename);   /* echo name of this file */
  100. #endif
  101.     cdp = (char *)NULL;
  102.     pp = name;                  /* point to translation buffer */
  103.     *name = '\0';               /* initialize buffer */
  104.     if (!jflag) {               /* -j => junk pathnames */
  105.         cdp = (char *)malloc(strlen(filename) + 13);  /* place for holding */
  106.         if (cdp == (char *)NULL) {                    /*  directory name */
  107.             fprintf(stderr, "mapname:  out of memory [%s]\n", filename);
  108.             return 3;
  109.         }
  110. #ifdef T20_VMS
  111.         *cdp++ = DIR_BEG;       /* '[' or '<' */
  112.         xp = cdp;               /* always points to last non-NULL char */
  113.         *cdp++ = '.';
  114. #endif /* T20_VMS */
  115. #ifdef MACOS
  116.         *cdp = ':';             /* the Mac uses ':' as a directory separator */
  117.         cdp[1] = '\0';
  118. #else /* !MACOS */
  119.         *cdp = '\0';
  120. #endif /* ?MACOS */
  121.     }
  122.  
  123. /*---------------------------------------------------------------------------
  124.     Begin main loop through characters in filename.
  125.   ---------------------------------------------------------------------------*/
  126.  
  127.     for (cp = filename; (workch = (unsigned char) *cp++) != 0  &&  !done;) {
  128.  
  129.         if (quote) {                 /* if char quoted, */
  130.             *pp++ = (char) workch;   /*  include it literally */
  131.             quote = FALSE;
  132.         } else if (indir) {          /* if in directory name, */
  133.             if (workch == (unsigned)delim)  /*  look for end delimiter */
  134.                 indir = FALSE;
  135.         } else
  136.             switch (workch) {
  137.             case '<':                /* discard DEC-20 directory name */
  138.                 indir = TRUE;
  139.                 delim = '>';
  140.                 break;
  141.             case '[':                /* discard VMS directory name */
  142.                 indir = TRUE;
  143.                 delim = ']';
  144.                 break;
  145.             case '/':                /* discard Unix path name  */
  146.             case '\\':               /*  or MS-DOS path name... */
  147.                                      /*  iff -j flag was given  */
  148.                 /*
  149.                  * Special processing case:  if -j flag was not specified on
  150.                  * command line and create_dirs is TRUE, create any necessary
  151.                  * directories included in the pathname.  Creation of dirs is
  152.                  * straightforward on BSD and MS-DOS machines but requires use
  153.                  * of the system() command on SysV systems (or any others which
  154.                  * don't have mkdir()).  The stat() check is necessary with
  155.                  * MSC because it doesn't have an EEXIST errno, and it saves
  156.                  * the overhead of multiple system() calls on SysV machines.
  157.                  */
  158.  
  159.                 if (!jflag) {
  160.                     *pp = '\0';
  161. #ifdef T20_VMS
  162.                     dp = name;
  163.                     while (*++xp = *dp++);  /* copy name to cdp */
  164.                     last_dot = NULL;        /* dir name:  no dots allowed */
  165.                     strcpy(xp, DIR_EXT);    /* add extension for stat check */
  166.                     stat_val = stat(cdp, &statbuf);
  167.                     *xp = '\0';             /* remove extension for all else */
  168.                     if (stat_val) {         /* doesn't exist, so create */
  169. #else /* !T20_VMS */
  170. #ifdef MSDOS
  171.                     if (last_dot != NULL) {  /* one dot in dir name is legal */
  172.                         *last_dot = '.';
  173.                         last_dot = NULL;
  174.                     }
  175. #endif /* MSDOS */
  176.                     strcat(cdp, name);
  177. #ifdef OS2
  178.                     if ((longdir = !IsFileNameValid(cdp)) != 0) {
  179.                         last = strrchr(cdp, '/');
  180.                         strcpy(longfilename, last ? last + 1 : cdp);
  181.                         fprintf(stderr, "renaming directory \"%s\"", cdp);
  182.                         ChangeNameForFAT(cdp);
  183.                         fprintf(stderr, " to \"%s\"\n", cdp);
  184.                     }
  185. #endif /* OS2 */
  186.                     if (stat(cdp, &statbuf)) {  /* doesn't exist, so create */
  187. #endif /* ?T20_VMS */
  188.                         if (!create_dirs) /* told not to create (freshening) */
  189.                             return 2;
  190. #ifdef NO_MKDIR
  191. #ifndef TOPS20 /* for now */
  192.                         sprintf(command,
  193.                           "IFS=\" \t\n\" /bin/mkdir %s 2>/dev/null", cdp);
  194.                         if (system(command)) {
  195. #else  /* TOPS20 */
  196.                         if (FALSE) {
  197. #endif /* ?TOPS20 */
  198. #else /* !NO_MKDIR */
  199.                         if (MKDIR(cdp, PERMS) == -1) {
  200. #endif /* ?NO_MKDIR */
  201.                             perror(cdp);  free(cdp);
  202.                             fprintf(stderr,
  203.                               "mapname:  unable to process [%s]\n", filename);
  204.                             return 3;
  205.                         }
  206.                         created = TRUE;
  207. #ifdef OS2
  208.                         if (longdir)
  209.                             SetLongNameEA(cdp, longfilename);
  210. #endif /* OS2 */
  211.                     } else if (!(statbuf.st_mode & S_IFDIR)) {
  212.                         fprintf(stderr,
  213.                           "mapname:  %s exists but is not a directory\n", cdp);
  214.                         free(cdp);
  215.                         fprintf(stderr, "mapname:  unable to process [%s]\n",
  216.                           filename);
  217.                         return 3;
  218.                     }
  219. #ifdef T20_VMS
  220.                     *xp = '/';  /* for now... (mkdir()) */
  221. #else /* !T20_VMS */
  222. #ifdef MACOS
  223.                     strcat(cdp, ":");
  224. #else /* !MACOS */
  225. #ifdef ATARI_ST
  226.                     strcat(cdp, "\\");
  227. #else /* !ATARI_ST */
  228.                     strcat(cdp, "/");
  229. #endif /* ?ATARI_ST */
  230. #endif /* ?MACOS */
  231. #endif /* ?T20_VMS */
  232.                 }
  233.                 pp = name;
  234.                 break;
  235.  
  236.             case ':':
  237. #ifdef UNIX                       /* colon is a valid character in Unix */
  238.                 *pp++ = workch;   /* filenames, so keep it; anywhere else, */
  239. #else /* !UNIX */                 /* change it to an underscore (node and */
  240.                 *pp++ = '_';      /* drive names not stored in zipfile) */
  241. #endif /* ?UNIX */
  242.                 break;
  243.  
  244.             case '.':             /* TOPS-20 generation number or */
  245. #ifdef DOS_T20_VMS                /*  DOS, VMS or TOPS-20 separator */
  246.                 last_dot = pp;    /* point at last dot so far... */
  247.                 *pp++ = '_';      /* convert dot to underscore */
  248. #else /* !DOS_T20_VMS */
  249.                 *pp++ = workch;
  250. #endif /* ?DOS_T20_VMS */
  251.                 break;
  252.  
  253.             case ';':             /* VMS generation or DEC-20 attrib */
  254. #ifdef MACOS
  255.                 if (V_flag || macflag)
  256. #else /* !MACOS */
  257.                 if (V_flag)                /* if requested, save VMS ";##" */
  258. #endif /* ?MACOS */                        /*  version info or Macintosh */
  259.                     *pp++ = (char)workch;  /*  (?) info; otherwise discard */
  260.                 else                       /*  everything starting with */
  261.                     done = TRUE;           /*  semicolon.  (Worry about */
  262.                 break;                     /*  TOPS-20 later.) */
  263.  
  264.             case '\026':          /* control-V quote for special chars */
  265.                 quote = TRUE;     /* set flag for next character */
  266.                 break;
  267.  
  268.             case ' ':
  269. #if defined(T20_VMS) || defined(MTS)
  270.                 *pp++ = '_';      /* change spaces to underscore under */
  271. #else /* !(T20_VMS || MTS) */     /*  VMS, TOPS-20 and MTS, and under */
  272. #ifdef DOS_OS2                    /*  DOS and OS/2 if -s not specified */
  273.                 if (!sflag)
  274.                     *pp++ = '_';
  275.                 else
  276. #endif /* DOS_OS2 */
  277.                 *pp++ = (char)workch;   /* Unix, etc.:  leave as spaces */
  278. #endif /* ?(T20_VMS || MTS) */
  279.                 break;
  280.  
  281.             default:
  282. #ifdef MACOS
  283.                 if ((macflag && ((unsigned)workch > 0x1F)) || isprint(workch))
  284. #else /* !MACOS */
  285. #if defined(DOS_OS2) || defined(UNIX)
  286.                 /* allow European characters in filenames: */
  287.                 if (isprint(workch) || (128 <= workch && workch <= 254))
  288. #else /* !(DOS_OS2 || UNIX) */
  289.                 if (isprint(workch))    /* other printable, just keep */
  290. #endif /* ?(DOS_OS2 || UNIX) */
  291. #endif /* ?MACOS */
  292.                     *pp++ = (char) workch;
  293.             } /* end switch */
  294.  
  295.     } /* end for loop */
  296.  
  297.     *pp = '\0';                   /* done with name:  terminate it */
  298. #ifdef DOS_T20_VMS                /*  and put a dot back in if VMS */
  299.     if (last_dot != NULL)         /*  or MS-DOS or TOPS-20 */
  300.         *last_dot = '.';
  301. #endif /* DOS_T20_VMS */
  302.  
  303. /*---------------------------------------------------------------------------
  304.     We COULD check for existing names right now, create a "unique" name, etc.
  305.     At present, we do this in extract_or_test_files() (immediately after we
  306.     return from here).  If conversion went bad, the name'll either be nulled
  307.     out (in which case we'll return non-0), or following procedures won't be
  308.     able to create the extracted file and other error messages will result.
  309.   ---------------------------------------------------------------------------*/
  310.  
  311.     if (filename[strlen(filename) - 1] == '/') {
  312.         /* A directory was extracted. It had a trailing /, 
  313.          * don't report the error below. */
  314.         if (created) {
  315.             printf("   Creating: %s", filename);
  316. #ifdef OS2
  317.             SetPathInfo(filename, lrec.last_mod_file_date,
  318.                                   lrec.last_mod_file_time, -1);
  319.             if (extra_field)
  320.                 SetEAs(filename, extra_field);
  321. #endif
  322.             printf("\n");
  323.         }
  324.         return 2; /* but skip file */
  325.     }
  326.  
  327.     if (*name == '\0') {
  328.         fprintf(stderr, "mapname:  conversion of [%s] failed\n", filename);
  329.         return 3;
  330.     }
  331.  
  332. #ifdef OS2
  333.     if (!longname && ((longname = !IsFileNameValid(name)) != 0)) {
  334.         /* in case of second call after user renamed the file, skip this */
  335.         last = strrchr(name, '/');      /* THIS time, save for file_io */
  336.         last = last ? last + 1 : name;  /* only last component */
  337.         strcpy(longfilename, last);
  338.         fprintf(stderr, "renaming \"%s\"", name);
  339.         ChangeNameForFAT(last);
  340.         fprintf(stderr, " to \"%s\"\n", name);
  341.     }
  342. #endif /* OS2 */
  343.  
  344. #ifdef VMS
  345.     /* convert filename to legal VMS one, substituting underscores for
  346.      * all invalid characters */
  347.     for (np = name;  *np;  ++np)
  348.         if (!(isdigit(*np) || isalpha(*np) || (*np == '$') ||
  349.             (*np == '-') || (*np == '_') || (*np == '.') || (*np == ';')))
  350.             *np = '_';
  351. #endif /* VMS */
  352.  
  353.     if (!jflag) {
  354. #ifdef T20_VMS
  355.         *xp++ = DIR_END;             /* proper end-of-dir-name delimiter */
  356.         if (xp == cdp) {             /* no path-name stuff, so... */
  357.             strcpy(filename, name);  /* copy file name into global and */
  358.             cdp -= 2;                /*   prepare to free malloc'd space */
  359.         } else {                     /* we've added path-name stuff... */
  360.             *xp = '\0';              /*   so terminate and convert to */
  361.             dp = cdp;                /*   VMS subdir separators (skip */
  362.             while (*++dp)            /*   first char:  better not be */
  363.                 if (*dp == '/')      /*   "/"):  change all slashes */
  364.                     *dp = '.';       /*   to dots */
  365.             cdp -= 2;                /*   include leading bracket and dot */
  366.             strcpy(filename, cdp);   /* copy VMS-style path name into global */
  367.             strcat(filename, name);  /* concatenate file name to global */
  368.         }
  369. #else /* !T20_VMS */
  370.         strcpy(filename, cdp);       /* either "" or slash-terminated path */
  371.         strcat(filename, name);      /* append file name to path name */
  372. #endif /* ?T20_VMS */
  373.         free(cdp);
  374.     } else
  375.         strcpy(filename, name);      /* copy converted name into global */
  376.  
  377. #if PATH_MAX < (FILNAMSIZ - 1)
  378.     /* check the length of the file name and truncate if necessary */
  379.     if (PATH_MAX < strlen(filename)) {
  380.         fprintf(stderr, "caution:  truncating filename\n");
  381.         filename[PATH_MAX] = '\0';
  382.         fprintf(stderr, "[ %s ]\n", filename);
  383.         return 1;             /* 1:  warning error */
  384.     }
  385. #endif
  386.  
  387.     return 0;
  388. }
  389.